package com.leyantech.ecp.agenx.web;

import com.leyantech.ecp.agenx.common.ClusterVerticle;
import com.leyantech.ecp.agenx.common.misc.HttpLocalRateLimiter;
import com.leyantech.ecp.agenx.common.misc.TracingHelper;
import com.leyantech.ecp.agenx.web.di.WebModule;
import com.leyantech.ecp.agenx.web.handler.AdminHandler;
import com.leyantech.ecp.agenx.web.handler.AuthHandler;
import com.leyantech.ecp.agenx.web.handler.TestWindowHandler;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Module;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.healthchecks.HealthCheckHandler;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.ErrorHandler;
import io.vertx.ext.web.handler.FaviconHandler;
import io.vertx.ext.web.handler.LoggerHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author eahau, {@literal <eahau@foxmail.com>}
 * @date 2022-10-31.
 */
@Slf4j
public class WebVerticle extends ClusterVerticle {

  @Inject
  private AuthHandler authHandler;

  @Inject
  private TestWindowHandler testWindowHandler;

  @Inject
  private AdminHandler adminHandler;

  @Override
  protected List<Module> dependentModules() {
    return Lists.newArrayList(new WebModule(), binder -> {
      binder.bind(HttpClient.class).toInstance(vertx.createHttpClient());
    });
  }

//  @Override
//  protected ClusterManager configClusterManager() {
//    // web 不需要加入集群
//    return null;
//  }

  private void warmup() {
    authHandler.warmup();
    testWindowHandler.warmup();
  }

  @Override
  public void start() {
    warmup();

    final Router router = Router.router(vertx);

    router.route()
        .handler(FaviconHandler.create(vertx))
        .handler(TracingHelper.tracingHandler(LoggerHandler.create()))
        .handler(
            new HttpLocalRateLimiter(context -> context.request().remoteAddress().hostAddress()))
        .handler(BodyHandler.create())
        .failureHandler(TracingHelper.tracingHandler(context -> {
          if (context.failed()) {
            log.error("handle failed, code {}", context.statusCode(), context.failure());
          }
          context.next();
        }))
        .failureHandler(TracingHelper.tracingHandler(ErrorHandler.create(vertx)));

    configHealthCheck(healthChecks -> {
      router.route("/health*").handler(HealthCheckHandler.createWithHealthChecks(healthChecks));
    });

    router.post("/auth").blockingHandler(TracingHelper.tracingHandler(authHandler));

    // 测试窗
    router.post("/testwin").blockingHandler(TracingHelper.tracingHandler(testWindowHandler));

    router.post("/admin").blockingHandler(TracingHelper.tracingHandler(adminHandler));

    final HttpServer httpServer = vertx.createHttpServer();
    httpServer.requestHandler(router)
        .listen(8080);
    addCloseHook(httpServer::close);

  }

  public static void main(String[] args) {
    new WebVerticle().startVerticle();
  }

}
